﻿using System;
using System.Collections.Generic;
using System.Linq;
using XCI.Sys.Model;
using XCI.Core;
using XCI.Extensions;
using XCI.Helper;
using XCI.Windows.Extensions;

namespace XCI.Sys.Service
{
    /// <summary>
    /// 系统用户服务
    /// </summary>
    public class UserService : BaseService<Model.SysUser>
    {
        public static readonly UserService Instance = new UserService();
        protected override string RootUrl => "/api/sys/user/";

        /// <summary>
        /// 新建用户模型
        /// </summary>
        public SysUser New()
        {
            return new SysUser
            {
                Id = NewId(),
                Admin = false,
                DeptId = string.Empty,
                LoginNumber = 0,
                Status = true
            };
        }

        /// <summary>
        /// 复制用户模型
        /// </summary>
        /// <param name="original">原模型</param>
        public SysUser Copy(SysUser original)
        {
            if (original == null) throw new ArgumentNullException(nameof(original));
            var model = original?.Clone();
            model.Id = NewId();
            model.Name = model.Name+" 复制";
            model.Account = model.Account + " 复制";
            model.RoleIds = RoleService.Instance.SelectListByUserId(original.Id).Select(p => p.Id).JoinString();
            return model;
        }

        /// <summary>
        /// 检查用户主键是否存在
        /// </summary>
        /// <param name="id">用户主键</param>
        public bool ExistById(string id)
        {
            return ExistByIdCore(id);
        }

        /// <summary>
        /// 检查部门主键是否存在
        /// </summary>
        /// <param name="deptId">部门主键</param>
        public bool ExistByDeptId(string deptId)
        {
            var url = GetUrl("existByDeptId", deptId);
            return SysRuntime.Api.Post<bool>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 检查用户账号是否存在
        /// </summary>
        /// <param name="account">用户账号</param>
        public bool ExistByAccount(string account)
        {
            var url = GetUrl("existByAccount", account);
            return SysRuntime.Api.Post<bool>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 检查账号登录是否需要验证码
        /// </summary>
        /// <param name="account">用户账号</param>
        public bool RequireCaptcha(string account)
        {
            var url = GetUrl("requireCaptcha", account);
            return SysRuntime.Api.PostAsMessage(url).Success;
        }

        /// <summary>
        /// 生成验证码
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="type">验证码类型,可用值:math,char</param>
        public byte[] Captcha(string account, string type = "math")
        {
            var url = GetUrl("captcha", account, type);
            return SysRuntime.Api.DownloadPost(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 验证用户
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="password">密码</param>
        /// <param name="captcha">验证码</param>
        /// <returns>成功返回True</returns>
        public BoolMessage ValidUser(string account, string password, string captcha)
        {
            var url = GetUrl("validUser");
            var data = Map.New
                .Add("account", account)
                .Add("password", password)
                .Add("captcha", captcha);
            return SysRuntime.Api.PostAsMessage(url, data);
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="account">账号</param>
        /// <param name="password">密码</param>
        /// <param name="captcha">验证码</param>
        public BoolMessage<SysUser> Login(string account, string password, string captcha)
        {
            var url = GetUrl("login");
            var data = Map.New
                 .Add("account", account)
                 .Add("password", password)
                 .Add("captcha", captcha);
            return SysRuntime.Api.Post<SysUser>(url, data);
        }

        /// <summary>
        /// 用户注销
        /// </summary>
        /// <param name="id">用户主键</param>
        public bool Logout(string id)
        {
            var url = GetUrl("logout", id);
            return SysRuntime.Api.PostAsMessage(url).EnsureSuccess().Success;
        }

        /// <summary>
        /// 新建用户
        /// </summary>
        /// <param name="model">用户模型对象</param>
        /// <returns>成功返回true</returns>
        public bool Insert(SysUser model)
        {
            return InsertCore(model);
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="model">用户模型对象</param>
        /// <returns>成功返回true</returns>
        public bool Update(SysUser model)
        {
            return UpdateCore(model);
        }

        /// <summary>
        /// 修改状态
        /// </summary>
        /// <param name="ids">主键字符串</param>
        /// <param name="status">状态,1启用;0禁用</param>
        /// <returns>成功返回true</returns>
        public bool UpdateStatus(string ids, bool status)
        {
            return UpdateStatusByIdsCore(ids, status);
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="ids">主键字符串</param>
        /// <param name="newPassword">新密码</param>
        /// <returns>成功返回true</returns>
        public bool RevisePassword(string ids, string newPassword)
        {
            var url = GetUrl("revisePassword");
            var map = Map.New.Add("ids", ids).Add("newPassword", newPassword);
            return SysRuntime.Api.PostAsMessage(url, map).EnsureSuccess().Success;
        }

        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="id">用户主键</param>
        /// <param name="currentPassword">当前密码</param>
        /// <param name="newPassword">新密码</param>
        /// <returns>成功返回true</returns>
        public bool ModifyPassword(string id, string currentPassword, string newPassword)
        {
            var url = GetUrl("modifyPassword");
            var map = Map.New.Add("id", id).Add("currentPassword", currentPassword).Add("newPassword", newPassword);
            return SysRuntime.Api.PostAsMessage(url, map).EnsureSuccess().Success;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="ids">主键字符串</param>
        /// <returns>成功返回true</returns>
        public bool Delete(string ids)
        {
            return DeleteByIdsCore(ids);
        }

        /// <summary>
        /// 根据主键获取用户对象
        /// </summary>
        /// <param name="id">用户主键</param>
        public SysUser SelectById(string id)
        {
            return SelectByIdCore(id);
        }

        /// <summary>
        /// 根据用户账号获取用户对象
        /// </summary>
        /// <param name="account">用户账号</param>
        /// <returns>成功返回模型对象</returns>
        public SysUser SelectByAccount(string account)
        {
            var url = GetUrl("selectByAccount", account);
            return SysRuntime.Api.Post<SysUser>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 获取指定角色中已关联的用户列表
        /// </summary>
        /// <param name="roleId">角色主键</param>
        public List<SysUser> SelectListByRoleId(string roleId)
        {
            var url = GetUrl("selectListByRoleId", roleId);
            return SysRuntime.Api.Post<List<SysUser>>(url).EnsureSuccess().Data;
        }

        /// <summary>
        /// 获取指定角色中已关联的用户列表
        /// </summary>
        /// <param name="roleId">角色主键</param>
        public List<SysUser> SelectUnListByRoleId(string roleId)
        {
            var url = GetUrl("selectUnListByRoleId", roleId);
            return SysRuntime.Api.Post<List<SysUser>>(url).EnsureSuccess().Data;
        }
        
        /// <summary>
        /// 查询用户分页列表
        /// </summary>
        /// <param name="paged">分页参数</param>
        /// <param name="key">编码/名称关键字</param>
        /// <param name="deptId">部门主键</param>
        /// <param name="status">状态(0:禁用;1:启用;null:全部记录)</param>
        public PageList<SysUser> SelectPageList(PageParam paged, string key, string deptId, bool? status)
        {
            var map = GetQueryMap(ToPageMap(paged), key, deptId, status);
            return SelectPageListCore(map);
        }

        /// <summary>
        /// 查询用户列表
        /// </summary>
        /// <param name="key">编码/名称关键字</param>
        /// <param name="deptId">部门主键</param>
        /// <param name="status">状态(0:禁用;1:启用;null:全部记录)</param>
        public List<SysUser> SelectList(string key, string deptId, bool? status)
        {
            var map = GetQueryMap(Map.New, key, deptId, status);
            return SelectListCore(map);
        }

        /// <summary>
        /// 查询简单用户列表
        /// </summary>
        /// <param name="key">编码/名称关键字</param>
        /// <param name="deptId">部门主键</param>
        /// <param name="status">状态(0:禁用;1:启用;null:全部记录)</param>
        public List<SysUserSimple> SelectSimpleList(string key, string deptId, bool? status)
        {
            var map = GetQueryMap(Map.New, key, deptId, status);
            var url = GetUrl("selectSimpleList");
            return SysRuntime.Api.Post<List<SysUserSimple>>(url, map).EnsureSuccess().Data;
        }

        /// <summary>
        /// 导出用户列表
        /// </summary>
        /// <param name="key">编码/名称关键字</param>
        /// <param name="deptId">部门主键</param>
        /// <param name="status">状态(0:禁用;1:启用;null:全部记录)</param>
        public byte[] Export(string key, string deptId, bool? status)
        {
            var map = GetQueryMap(Map.New, key, deptId, status);
            return ExportCore(map);
        }

        /// <summary>
        /// 刷新服务端用户缓存
        /// </summary>
        public bool RefreshCache()
        {
            return RefreshCacheCore();
        }

        private Map GetQueryMap(Map map, string key, string deptId, bool? status)
        {
            return map
                .Add("key", key)
                .Add("deptId", deptId)
                .Add("status", status);
        }
    }
}
